using DeviceRepairWorkflow.Api.Data;
using DeviceRepairWorkflow.Api.Models;
using Elsa.Workflows.Runtime.Contracts;
using Elsa.Workflows.Runtime.Requests;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;

namespace DeviceRepairWorkflow.Api.Controllers;

[ApiController]
[Route("api/[controller]")]
public class RepairRequestsController : ControllerBase
{
    private readonly ApplicationDbContext _context;
    private readonly IWorkflowDispatcher _workflowDispatcher;

    public RepairRequestsController(ApplicationDbContext context, IWorkflowDispatcher workflowDispatcher)
    {
        _context = context;
        _workflowDispatcher = workflowDispatcher;
    }

    [HttpGet]
    public async Task<ActionResult<IEnumerable<RepairRequest>>> GetRepairRequests()
    {
        return await _context.RepairRequests
            .Include(r => r.Device)
            .OrderByDescending(r => r.CreatedAt)
            .ToListAsync();
    }

    [HttpGet("{id}")]
    public async Task<ActionResult<RepairRequest>> GetRepairRequest(int id)
    {
        var repairRequest = await _context.RepairRequests
            .Include(r => r.Device)
            .FirstOrDefaultAsync(r => r.Id == id);

        if (repairRequest == null)
        {
            return NotFound();
        }

        return repairRequest;
    }

    [HttpPost]
    public async Task<ActionResult<RepairRequest>> CreateRepairRequest(RepairRequest repairRequest)
    {
        repairRequest.CreatedAt = DateTime.Now;
        repairRequest.Status = RepairStatus.Pending;

        _context.RepairRequests.Add(repairRequest);
        await _context.SaveChangesAsync();

        return CreatedAtAction(nameof(GetRepairRequest), new { id = repairRequest.Id }, repairRequest);
    }

    [HttpPost("{id}/start-workflow")]
    public async Task<ActionResult> StartWorkflow(int id, [FromBody] RepairWorkflowStartRequest request)
    {
        var repairRequest = await _context.RepairRequests.FindAsync(id);
        if (repairRequest == null)
        {
            return NotFound();
        }

        // Create workflow instance
        var workflowInstance = new WorkflowInstance
        {
            RepairRequestId = id,
            CurrentStep = "DecisionPending",
            Status = WorkflowStatus.Running,
            CreatedAt = DateTime.Now,
            CreatedBy = request.CurrentUser
        };

        _context.WorkflowInstances.Add(workflowInstance);
        
        // Update repair request status
        repairRequest.Status = RepairStatus.DecisionPending;
        
        await _context.SaveChangesAsync();

        // Start Elsa workflow
        var workflowInput = new Dictionary<string, object>
        {
            ["RepairRequestId"] = id,
            ["DeviceId"] = repairRequest.DeviceId,
            ["RequestedBy"] = repairRequest.RequestedBy,
            ["WorkflowInstanceId"] = workflowInstance.Id
        };

        var startWorkflowRequest = new DispatchWorkflowDefinitionRequest
        {
            DefinitionId = "DeviceRepairWorkflow",
            Input = workflowInput
        };

        // For now, we'll handle the workflow logic directly in the controller
        // Later we can integrate with Elsa properly
        var result = await _workflowDispatcher.DispatchAsync(startWorkflowRequest);

        return Ok(new { 
            Success = true, 
            WorkflowInstanceId = workflowInstance.Id,
            Message = "Workflow started successfully"
        });
    }

    public class RepairWorkflowStartRequest
    {
        public string CurrentUser { get; set; } = string.Empty;
    }

    [HttpPut("{id}")]
    public async Task<IActionResult> UpdateRepairRequest(int id, RepairRequest repairRequest)
    {
        if (id != repairRequest.Id)
        {
            return BadRequest();
        }

        _context.Entry(repairRequest).State = EntityState.Modified;

        try
        {
            await _context.SaveChangesAsync();
        }
        catch (DbUpdateConcurrencyException)
        {
            if (!RepairRequestExists(id))
            {
                return NotFound();
            }
            throw;
        }

        return NoContent();
    }

    [HttpPost("{id}/approve")]
    public async Task<IActionResult> ApproveRepairRequest(int id)
    {
        var repairRequest = await _context.RepairRequests.FindAsync(id);
        if (repairRequest == null)
        {
            return NotFound();
        }

        repairRequest.Status = RepairStatus.Approved;
        await _context.SaveChangesAsync();

        // For now, just update the status
        // We can add workflow triggering later

        return NoContent();
    }

    [HttpPost("{id}/reject")]
    public async Task<IActionResult> RejectRepairRequest(int id, [FromBody] string reason)
    {
        var repairRequest = await _context.RepairRequests.FindAsync(id);
        if (repairRequest == null)
        {
            return NotFound();
        }

        repairRequest.Status = RepairStatus.Rejected;
        repairRequest.Notes = reason;
        await _context.SaveChangesAsync();

        // For now, just update the status
        // We can add workflow triggering later

        return NoContent();
    }

    [HttpDelete("{id}")]
    public async Task<IActionResult> DeleteRepairRequest(int id)
    {
        var repairRequest = await _context.RepairRequests.FindAsync(id);
        if (repairRequest == null)
        {
            return NotFound();
        }

        _context.RepairRequests.Remove(repairRequest);
        await _context.SaveChangesAsync();

        return NoContent();
    }

    private bool RepairRequestExists(int id)
    {
        return _context.RepairRequests.Any(e => e.Id == id);
    }
} 